home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / admin / shadow-9.tar / shadow-9 / shadow-960129 / chpasswd.c < prev    next >
C/C++ Source or Header  |  1995-12-17  |  7KB  |  247 lines

  1. /*
  2.  * Copyright 1990 - 1994, John F. Haugh II
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by John F. Haugh, II
  16.  *      and other contributors.
  17.  * 4. Neither the name of John F. Haugh, II nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY JOHN HAUGH AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL JOHN HAUGH OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  *
  33.  * chpasswd - update passwords in batch
  34.  *
  35.  *    chpasswd reads standard input for a list of colon separated
  36.  *    user names and new passwords.  the appropriate password
  37.  *    files are updated to reflect the changes.  because the
  38.  *    changes are made in a batch fashion, the user must run
  39.  *    the mkpasswd command after this command terminates since
  40.  *    no password updates occur until the very end.
  41.  */
  42.  
  43. #include <stdio.h>
  44. #include "config.h"
  45. #include "prototypes.h"
  46. #include "defines.h"
  47. #include "pwd.h"
  48. #include <fcntl.h>
  49. #ifdef    SHADOWPWD
  50. #include "shadow.h"
  51. #endif
  52.  
  53. #ifndef    lint
  54. static char rcsid[] = "$Id: chpasswd.c,v 1.3 1995/12/17 05:04:49 marekm Exp $";
  55. #endif
  56.  
  57. char    *Prog;
  58.  
  59. extern    char    *pw_encrypt();
  60. extern    char    *l64a();
  61.  
  62. /* 
  63.  * If it weren't for the different structures and differences in how
  64.  * certain fields were manipulated, I could just use macros to replace
  65.  * the function calls for the different file formats.  So I make the
  66.  * best of things and just use macros to replace a few of the calls.
  67.  */
  68.  
  69. #ifdef    SHADOWPWD
  70. #define    pw_lock        spw_lock
  71. #define    pw_open        spw_open
  72. #define    pw_close    spw_close
  73. #define    pw_unlock    spw_unlock
  74. #endif
  75.  
  76. /*
  77.  * usage - display usage message and exit
  78.  */
  79.  
  80. void usage ()
  81. {
  82.     fprintf (stderr, "usage: %s\n", Prog);
  83.     exit (1);
  84. }
  85.  
  86. int main (argc, argv)
  87. int    argc;
  88. char    **argv;
  89. {
  90.     char    buf[BUFSIZ];
  91.     char    *name;
  92.     char    *newpwd;
  93.     char    *cp;
  94. #ifdef    SHADOWPWD
  95.     struct    spwd    *sp;
  96.     struct    spwd    newsp;
  97.     struct    spwd    *spw_locate();
  98. #else
  99.     struct    passwd    *pw;
  100.     struct    passwd    newpw;
  101.     struct    passwd    *pw_locate();
  102.     char    newage[5];
  103. #endif
  104.     int    errors = 0;
  105.     int    line = 0;
  106.     long    now = time ((long *) 0) / (24L*3600L);
  107.  
  108.     Prog = basename(argv[0]);
  109.  
  110.     if (argc != 1)
  111.         usage ();
  112.  
  113.     /*
  114.      * Lock the password file and open it for reading.  This will
  115.      * bring all of the entries into memory where they may be
  116.      * updated.
  117.      */
  118.  
  119.     if (! pw_lock ()) {
  120.         fprintf (stderr, "%s: can't lock password file\n", Prog);
  121.         exit (1);
  122.     }
  123.     if (! pw_open (O_RDWR)) {
  124.         fprintf (stderr, "%s: can't open password file\n", Prog);
  125.         exit (1);
  126.     }
  127.  
  128.     /*
  129.      * Read each line, separating the user name from the password.
  130.      * The password entry for each user will be looked up in the
  131.      * appropriate file (shadow or passwd) and the password changed.
  132.      * For shadow files the last change date is set directly, for
  133.      * passwd files the last change date is set in the age only if
  134.      * aging information is present.
  135.      */
  136.  
  137.     while (fgets (buf, sizeof buf, stdin) != (char *) 0) {
  138.         line++;
  139.         if ((cp = strrchr (buf, '\n'))) {
  140.             *cp = '\0';
  141.         } else {
  142.             fprintf (stderr, "%s: line %d: line too long\n",
  143.                 Prog, line);
  144.             errors++;
  145.             continue;
  146.         }
  147.  
  148.         /*
  149.          * The username is the first field.  It is separated
  150.          * from the password with a ":" character which is
  151.          * replaced with a NUL to give the new password.  The
  152.          * new password will then be encrypted in the normal
  153.          * fashion with a new salt generated.
  154.          */
  155.  
  156.         name = buf;
  157.         if ((cp = strchr (name, ':'))) {
  158.             *cp++ = '\0';
  159.         } else {
  160.             fprintf (stderr, "%s: line %d: missing new password\n",
  161.                 Prog, line);
  162.             errors++;
  163.             continue;
  164.         }
  165.         newpwd = cp;
  166.         cp = pw_encrypt (newpwd, (char *) 0);
  167.  
  168.         /*
  169.          * Get the password file entry for this user.  The user
  170.          * must already exist.
  171.          */
  172.  
  173. #ifdef    SHADOWPWD
  174.         if (! (sp = spw_locate (name)))
  175. #else
  176.         if (! (pw = pw_locate (name)))
  177. #endif
  178.         {
  179.             fprintf (stderr, "%s: line %d: unknown user %s\n",
  180.                 Prog, line, name);
  181.             errors++;
  182.             continue;
  183.         }
  184.  
  185.         /*
  186.          * The freshly encrypted new password is merged into
  187.          * the user's password file entry and the last password
  188.          * change date is set to the current date.
  189.          */
  190.  
  191. #ifdef    SHADOWPWD
  192.         newsp = *sp;
  193.         newsp.sp_pwdp = cp;
  194.         newsp.sp_lstchg = now;
  195. #else
  196.         newpw = *pw;
  197.         newpw.pw_passwd = cp;
  198. #ifdef    ATT_AGE
  199.         if (newpw.pw_age[0]) {
  200.             strcpy (newage, newpw.pw_age);
  201.             strcpy (newage + 2, l64a (now / 7));
  202.             newpw.pw_age = newage;
  203.         }
  204. #endif
  205. #endif
  206.  
  207.         /* 
  208.          * The updated password file entry is then put back
  209.          * and will be written to the password file later, after
  210.          * all the other entries have been updated as well.
  211.          */
  212.  
  213. #ifdef    SHADOWPWD
  214.         if (! spw_update (&newsp))
  215. #else
  216.         if (! pw_update (&newpw))
  217. #endif
  218.         {
  219.             fprintf (stderr, "%s: line %d: cannot update password entry\n",
  220.                 Prog, line);
  221.             errors++;
  222.             continue;
  223.         }
  224.     }
  225.  
  226.     /*
  227.      * Any detected errors will cause the entire set of changes
  228.      * to be aborted.  Unlocking the password file will cause
  229.      * all of the changes to be ignored.  Otherwise the file is
  230.      * closed, causing the changes to be written out all at
  231.      * once, and then unlocked afterwards.
  232.      */
  233.  
  234.     if (errors) {
  235.         fprintf (stderr, "%s: error detected, changes ignored\n", Prog);
  236.         pw_unlock ();
  237.         exit (1);
  238.     }
  239.     if (! pw_close ()) {
  240.         fprintf (stderr, "%s: error updating password file\n", Prog);
  241.         exit (1);
  242.     }
  243.     (void) pw_unlock ();
  244.  
  245.     return (0);
  246. }
  247.